package com.itfitness.lockview.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;

/**
 * @ProjectName: LockView
 * @Package: com.itfitness.lockview.widget
 * @ClassName: LockView
 * @Description: java类作用描述 ：控件锁
 * @Author: 作者名：lml
 * @CreateDate: 2019/3/6 14:38
 * @UpdateUser: 更新者：
 * @UpdateDate: 2019/3/6 14:38
 * @UpdateRemark: 更新说明：
 * @Version: 1.0
 */

public class LockView extends View {
    private Paint mPaintOuterFill;//外圆填充画笔
    private Paint mPaintOuterStrok;//外圆描边画笔
    private Paint mPaintInner;//内圆画笔
    private Paint mPaintLine;//连线的画笔
    private float mOuterStrokWidth = 3;//外圆描边宽度
    private int mRowCount = 3;//行数
    private int mColumnCount = 3;//列数
    private ArrayList<LockItem> mLockItems;//锁圆圈集合
    private int mColorSuccess = Color.parseColor("#29FA72");//解锁成功的颜色
    private int mColorFailure = Color.parseColor("#F33714");//解锁失败的颜色
    private int mColorUnSelect = Color.GRAY;//未选中的颜色
    private int mColorOuterFill = Color.WHITE;//选中时外圆的填充颜色
    private int mColorSelect = Color.parseColor("#13DAED");//选中的颜色
    private int mColorShow = mColorSelect;//这个颜色是解锁时、验证密码成功或失败的颜色、默认是选中时的颜色（这个颜色会根据不同状态来回切换）
    private float mOuterRadius,mInnerRadius;
    private Path mLinePathSelect;//连线的路径
    private PointF mPrePoint;//手指连接的上一个点
    private PointF mPointTouch;//手指触摸的点
    private ArrayList<Integer> mLockSelectPassRecord;//按顺序记录选中的连接点
    private int[] mPass = {0,1,2,4,6,7,8};//正确的密码
    private CheckPasswordCallBack checkPasswordCallBack;

    public void setPass(int[] mPass) {
        this.mPass = mPass;
    }

    public void addCheckPasswordCallBack(CheckPasswordCallBack checkPasswordCallBack) {
        this.checkPasswordCallBack = checkPasswordCallBack;
    }

    public LockView(Context context) {
        this(context,null);
    }

    public LockView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public LockView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mPaintOuterFill = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintOuterFill.setStyle(Paint.Style.FILL);
        mPaintOuterFill.setColor(mColorOuterFill);

        mPaintOuterStrok = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintOuterStrok.setStyle(Paint.Style.STROKE);
        mPaintOuterStrok.setStrokeWidth(mOuterStrokWidth);

        mPaintInner = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintInner.setStyle(Paint.Style.FILL);

        mPaintLine = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintLine.setStyle(Paint.Style.STROKE);
        mPaintLine.setStrokeJoin(Paint.Join.ROUND);
        mPaintLine.setStrokeCap(Paint.Cap.ROUND);

        mLockItems = new ArrayList<>();
        mLockSelectPassRecord = new ArrayList<>();

        mLinePathSelect = new Path();
        mPrePoint = new PointF(0,0);
        mPointTouch = new PointF(0,0);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mOuterRadius = w / (mColumnCount + 1)/2;//外圆的半径
        mInnerRadius = mOuterRadius/3;//内圆半径
        mPaintLine.setStrokeWidth(mInnerRadius*2/3*2);//连线的宽度为内圆直径的2/3
        initLockItems();
    }

    /**
     * 添加锁Item
     */
    private void initLockItems() {
        if(mLockItems==null){
            mLockItems = new ArrayList<>();
        }
        mLockItems.clear();
        //行
        for(int x = 0;x < mRowCount;x++){
            float circleY;//Y轴坐标
            if(x == 0){
                //第一行
                circleY = mOuterRadius + mOuterRadius/2;
            }else {
                circleY = (mOuterRadius*2 + mOuterRadius/2)*x+mOuterRadius + mOuterRadius/2;//(mOuterRadius*2 + mOuterRadius/2)为大于第一行的圆心与上一行圆心的距离，mOuterRadius + mOuterRadius/2则为第一行圆心与控件顶部的距离
            }
            //列
            for(int y = 0;y < mColumnCount;y++){
                float circleX;//X轴坐标
                if(y == 0){
                    //第一行
                    circleX= mOuterRadius + mOuterRadius/2;
                }else {
                    circleX = (mOuterRadius*2 + mOuterRadius/2)*y+mOuterRadius + mOuterRadius/2;
                }
                LockItem lockItem = new LockItem();
                PointF pointF = new PointF(circleX,circleY);
                RectF rectFInner = new RectF(circleX - mInnerRadius,circleY - mInnerRadius,circleX+mInnerRadius,circleY+mInnerRadius);
                lockItem.setCircleCenter(pointF);
                lockItem.setRectFInnerCircle(rectFInner);
                mLockItems.add(lockItem);
            }
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for(LockItem lockItem:mLockItems){
            PointF circleCenter = lockItem.getCircleCenter();
            if(lockItem.isSelect){
                mPaintOuterStrok.setColor(mColorShow);
                mPaintInner.setColor(mColorShow);
                canvas.drawCircle(circleCenter.x,circleCenter.y,mOuterRadius, mPaintOuterFill);//画外圆填充
            }else {
                mPaintOuterStrok.setColor(mColorUnSelect);
                mPaintInner.setColor(mColorUnSelect);
            }
            canvas.drawCircle(circleCenter.x,circleCenter.y,mOuterRadius, mPaintOuterStrok);//画外圆
            canvas.drawCircle(circleCenter.x,circleCenter.y,mInnerRadius, mPaintInner);//画内圆
        }

        mPaintLine.setColor(mColorShow);
        mPaintLine.setAlpha(100);//设置连线半透明
        if(mPrePoint.x!=0&&mPointTouch.x!=0){
            canvas.drawLine(mPrePoint.x,mPrePoint.y,mPointTouch.x,mPointTouch.y,mPaintLine);//画点与手指间的连线
        }

        if(!mLinePathSelect.isEmpty()){
            canvas.drawPath(mLinePathSelect,mPaintLine);//画点与点间的连线
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                clearData();
                mPointTouch.x = event.getX();
                mPointTouch.y = event.getY();
                isPointOnInnerCircle(event);
                return true;
            case MotionEvent.ACTION_MOVE:
                mPointTouch.x = event.getX();
                mPointTouch.y = event.getY();
                isPointOnInnerCircle(event);
                break;
            case MotionEvent.ACTION_UP:
                mPointTouch.x = 0;//清除手指的连线，只剩下点之间的连线
                mPrePoint.x =0;
                //验证密码
                boolean checkResult = checkPass();
                if(checkResult){
                    //密码校验成功
                    mColorShow = mColorSuccess;//将选中的颜色设置为成功色
                    if(checkPasswordCallBack!=null){
                        checkPasswordCallBack.onSuccess();
                    }
                }else {
                    //密码校验失败
                    mColorShow = mColorFailure;//将选中的颜色设置为失败色
                    if(checkPasswordCallBack!=null){
                        checkPasswordCallBack.onFailure();
                    }
                }
                invalidate();
                break;
        }
        return super.onTouchEvent(event);
    }

    /**
     * 验证密码的正确与否
     */
    private boolean checkPass() {
        if(mPass==null||mPass.length<=0){
            return false;
        }
        if(mLockSelectPassRecord==null||mLockSelectPassRecord.size()<=0){
            return false;
        }
        if(mPass.length!=mLockSelectPassRecord.size()){
            return false;
        }else {
            boolean checkResult = true;//验证结果
            for (int i =0;i<mPass.length;i++){
                if(mPass[i]!=mLockSelectPassRecord.get(i)){//只要有一个不一样那就是错误了
                    checkResult=false;
                    break;
                }
            }
            return checkResult;
        }
    }

    /**
     * 再次进行连接的时候对数据进行重置
     */
    private void clearData() {
        if(mPointTouch.x == 0){
            mLinePathSelect.reset();//再次点击的时候清除点连接路径
            mLockSelectPassRecord.clear();//再次点击的时候清除连接位置（即连接密码）
            mColorShow=mColorSelect;//将展示的颜色恢复默认
            lockItemReset();
        }
    }

    /**
     * 恢复锁Item的未选中状态
     */
    private void lockItemReset() {
        for(LockItem lockItem:mLockItems){
            lockItem.isSelect = false;
        }
    }

    public void isPointOnInnerCircle(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        boolean isContains = false;
        PointF pointFCircleCenter = null;//如果在内圆中心范围的话将线连接到内圆中心
        for(int i = 0;i<mLockItems.size();i++){
            LockItem lockItem = mLockItems.get(i);
            RectF rectFInnerCircle = lockItem.getRectFInnerCircle();
            if(!lockItem.isSelect){//只对未连接的点处理
                if(rectFInnerCircle.contains(x,y)){
                    isContains = true;
                    pointFCircleCenter = lockItem.getCircleCenter();
                    lockItem.isSelect = true;
                    mLockSelectPassRecord.add(i);//添加选中的位置
                    break;
                }
            }
        }
        if(isContains){
            if(mLinePathSelect.isEmpty()){
                mLinePathSelect.moveTo(pointFCircleCenter.x,pointFCircleCenter.y);
            }else {
                mLinePathSelect.lineTo(pointFCircleCenter.x,pointFCircleCenter.y);
            }
            mPrePoint.x = pointFCircleCenter.x;
            mPrePoint.y = pointFCircleCenter.y;
        }
        invalidate();
    }

    /**
     * 锁Item
     */
    class LockItem{
        private RectF rectFInnerCircle;//内部圆的矩形（用于判断手指是否连接）
        private PointF circleCenter;//圆的中心点
        private boolean isSelect = false;//是否选中

        public RectF getRectFInnerCircle() {
            return rectFInnerCircle;
        }

        public void setRectFInnerCircle(RectF rectFInnerCircle) {
            this.rectFInnerCircle = rectFInnerCircle;
        }

        public PointF getCircleCenter() {
            return circleCenter;
        }

        public void setCircleCenter(PointF circleCenter) {
            this.circleCenter = circleCenter;
        }

        public boolean isSelect() {
            return isSelect;
        }

        public void setSelect(boolean select) {
            isSelect = select;
        }
    }

    /**
     * 验证密码的回调
     */
    public interface CheckPasswordCallBack{
        void onFailure();//成功
        void onSuccess();//失败
    }
}
